Cory Adams, Chris Boomhower, Alexandra Fisher, Alex Frye

MSDS 7333, October 25, 2017

NOTE: Answering Q.10: We have seen that the 1999 runners were typically older than the 2012 runners. Compare the age distribution of the runners across all 14 years of the races. Use quantile- quantile plots, boxplots, and density curves to make your comparisons. How do the distributions change over the years? Was it a gradual change?

Abstract

In this case study, race results for the Cherry Blossom Ten Mile Run from 1999 to 2012 are used to study how people’s physical performance changes with age [1]. The focus of the study involves scraping the Web for free and publicly published data and then getting that data into the correct format. In order to investigate how age distributions change over the years, age distribution for all runners across 14 years is compared; however, what information is recorded and how the data is formatted changes each year so close attention is paid first to formatting the data. The R language is leveraged to appropriately format the data via statistical analysis and examining summary statistics and plots. Following data acquisition and successfully reading tables of race results into R, results are analyzed and compared using density curves, quantile-quantile plots, and boxplots. In this way, we are able to visualize the data for tens of thousands of observations to explore the performance-age relationship and ultimately examine age distribution. For the general population of male runners, we find a right-skewed distribution in age with the highest frequency of runners falling into the 30-40 year age bin. Findings support original observations that age steadily decreases in both mean and median values. Final comparisons of age distribution across all 14 years using density curves, quantile-quantile plots, and boxplots definitely reveal an overall gradual decline in the age of runners over time. However, we speculate this decline will slow moving into the future just as we have seen from 2008 to 2012.

Introduction

This case study was undertaken in order to explore and shed light on the complex relationship between a person’s age and physical performance. Data used comes from the infamous Credit Union Cherry Blossom race. The Cherry Blossom Ten Mile Run is held every year during the month of April in Washington, D.C. when cherry blossom trees are said to bloom. Race results for the Cherry Blossom Ten Mile Run are available to the public online at http://www.cherryblossom.org/ and currently include annual results spanning from 1999 to 2012 (14 years in total). The race began in 1973 and has since grown by tens of thousands of runners to 17,000 entries in 2012 with ages ranging from 9 to 89. In fact, the race has been in such high demand that runners are chosen via a lottery system to enter the race. Because of the enormous amount of observations there is a clear abundance of information that can be used as a resource for investigating the performance-age relationship.

To that end, while this information is free and available to the public, what information is reported and how the data is formatted changes each year, presenting a challenge that must first be overcome before conducting further analysis. Therefore, after data cleanup is performed and race results data tables are read into R, we then turn our focus to the age distribution of runners across all 14 years of the races, as we have seen that the 1999 runners were typically older than the 2012 runners [1]. This is achieved by creating visual representations of the data through density curves, quantile-quantile plots, and boxplots. These visualizations are important for gaining deeper insights by seeing how fast or gradual changes are over time, as well as any outliers or subtle trends. For the purposes of this case study, only these three categories of plots are considered for only male runners and compared for a final analysis to ultimately determine how the distributions change over the years and if the changes was gradual.

Methods

The steps used for this analysis were: 1) data acquisition; 2) additional data cleanup for outlier removal; 3) density curves analysis; 4) quantile-quantile plots analysis; and 5) boxplots analysis.

Note that code used includes modified versions of R code function examples found in Data Science in R: A Case Studies Approach to Computational Reasoning and Problem Solving, Chapter 2, pages 47-100 [1].

Results

Data Acquisition

To begin, we utilized methods provided in the Data Science in R text to load male runners from 1999 to 2012. As the purpose of this analysis is to research this data post load, we have excluded the scraping process from this analysis and the data is loaded external to the notebook in the DataExtractAndClean.R file allowing us to focus on our analysis of age distributions.

Data Cleanup for Outlier Removal

Before beginning our analysis of age distributions, we have some preliminary data cleanup to perform on multiple scenarios, as this analysis is meant to represent the general population less outliers. First, there is 1 observation which appears to contain an outlier for its run-time; a 70 year old with a run-time of 1.5 which is likely either due to a non-starter or a data entry error.

Second, we identify 21 observations which have null values for age. These records are unable to be visualized for age distributions, and thus removed as well.

Lastly, we identify 10 observations with an age less than 10. Although there could be a young child in the run, there are several of these values with an age between 0 and 4, leaving us untrusting of the other three values remaining for 8 and 9 year olds. Due to this, we have decide to cut off the age lower limit at 10 years old to describe general population.

cbMenSub = cbMen[cbMen$runTime > 30 & !is.na(cbMen$age) & cbMen$age >= 10, ]

With these few outliers removed, we transform from 70070 to 70038 observations. We are now ready to move forward with our analysis of age distributions amongst each year.

Density Curve

To begin our density curve analysis, we first were interested in the overall distribution of age in the population across all years. Across all 14 years, the mean age is 38.611311, whereas the median age is 37. This suggests, since the mean value is larger than the median, that we have a slightly right-skewed distribution. Breaking age into bins of decade groups (10-20, 20-30,…,70,80, etc.), we are able to visualize the overall distribution of age. These bin counts help further these findings, with our most frequency bin including ages 30-40, the same identified for mean and median age. The distribution of bin counts also further supports the right-skew distribution as there is a slightly longer tail from 40-90 in comparison to that between 10-30.

ageCat = cut(cbMenSub$age, breaks = c(seq(10, 80, 10), 90))
bins=as.data.frame(table(ageCat))
bins.p <-ggplot(bins, aes(x=ageCat, y=Freq)) + geom_bar(stat="identity")
bins.p<-ggplotly(bins.p)
bins.p

To further this analysis, we are interested to see how age distribution has changed over the many years this race has been conducted. Below is a stacked density plot, providing a single curve for every year. Noteworthy to mention, the plot provided is rendered with plotly, allowing interactive hover values, zoom controls, and toggling of years to display by clicking on the legend. Before targetting specific years, there appears to be a notable decrease in mean age from 1999 to recent years. Additionally, earlier years appear to have a much more normal distribution in age than that of recent years.

By clicking on individual legend years {1999, 2004, 2008, 2012}, we may de-clutter the visual for further research into these findings on a wide spread of year runs. The mean age may be seen in the table below.

Year Mean Age
1999 40.3352148
2004 39.3128008
2008 37.7835732
2012 37.7528856

As was originally gleamed, ages steadily decrease from a mean of 40.3352148 to 37.7528856 years old. as the density curves also suggest, we observe the curves shift positions from right to left and density skewness elongate as we progress from early to recent years. These findings confirm our original observations, indicating that the core demographic for participating runners are decreasing year after year. We speculate this decrease will slow down moving forward, just as was seen from 2008 to 2012, with only a 0.0306877 difference in mean age in those years since participants under 20 have been insignificant across all years of the race. Although the mean distribution is shifting left, it is apparent that participation amongst the age groups above 40 have not significantly decreased. Because of this, we begin seeing the right-skew distribution increase in the most recent years of the race.

# Subset in order to color by year
cbMensPlot <- cbMenSub
cbMensPlot$year <- as.character(cbMensPlot$year)
age.d = ggplot(cbMensPlot, aes(age, color = year)) + geom_density() + scale_x_continuous(breaks = pretty(cbMensPlot$age, n = 10))
age.d = ggplotly(age.d) #Convert to plotly version
age.d

Quantile-Quantile Plots

Next in our analysis, we are interested to further build our case on normality of age distributions across the many years of the race. To do this, we decide to produce a Quantile-Quantile Plot (QQPlot) to assess our data’s quantiles against a theoretical normal distribution quantile. If our data poses as perfectly normal, we would see a straight line. The more our scatter varies from the ideal line, the further from normality is the distribution.

In efforts to create an interactive plotly visualization for these QQPlots as was done for density curves, the rendering was overbearing in terms of performance. Due to these issues, the stacked (static) ggplot visual is provided, however very difficult to gleam insights from. It is apparent that several of these years have normality problems, however very difficult to understand which years the plot references.

# calculate the normal theoretical quantiles per group
cbMensPlotQQ <- ddply(.data = cbMensPlot, .variables = .(year),
                      function(dsub){
                          q <- qqnorm(dsub$age, plot = FALSE)
                          dsub$xq <- q$x
                          dsub
                      })
age.qq = ggplot(data = cbMensPlotQQ, aes(x = xq, y = age, color = year)) +
                geom_point() +
                geom_smooth(method = "lm", se = FALSE) +
                xlab("Normal Theoretical Quantiles") +
                ylab("Normal Data Quantiles")
#age.qq = ggplotly(age.qq)
age.qq

To mitigate these issues, we build ggplot rendering of each year individually below in order to assess individually in comparison to the others. Although none of these plots provide us with a “perfect” line representing normality, we can assert that over time the distributions for age become less normal. Looking at the same years {1999,2004, 2008, 2012} as was done previously, we see very strong normality between ~30-60 years of age in the 1999 race. Moving towards 2004, we begin to see the scatter dip below the normality line, and a larger variation under 30 than was seen before. In 2008, we once again see the scatter dropping below the normality line, and increasing variance in both ages under 30 and those above 50 years old. Finally, in 2012, we see variation amongst the majority of the scatter and the normality line. These results help to further support those findings provided from density curves, in that normality in age distributions has began to shift. In recent years, we begin to have a skewed distribution, likely caused by the increased participation of the younger individuals.

plot.list <- list()
i = 1
#color.vect <- c('#D32F2F', '#C2185B', '#7B1FA2', '#512DA8', '#303F9F', '#1976D2', '#0288D1',
#                '#0097A7', '#00796B', '#388E3C', '#689F38', '#AFB42B', '#FBC02D', '#FFA000')
for(yr in unique(cbMensPlot$year)){
    cbMensPlotQQ <- ddply(.data = subset(cbMensPlot, cbMensPlot$year == yr), .variables = .(year),
                          function(dsub){
                              q <- qqnorm(dsub$age, plot = FALSE)
                              dsub$xq <- q$x
                              dsub
                          })
    
    age.qq = ggplot(data = cbMensPlotQQ, aes(x = xq, y = age, color = year)) +
                    geom_point() +
                    geom_smooth(method = "lm", se = FALSE) +
                    xlab("Normal Theoretical Quantiles") +
                    ylab("Normal Data Quantiles")
    
    #ggplot doesn't like to evaluate vector indexed contents so having to explicitly write color values line-by-line
    if(i==1) plot.list[[i]] <- age.qq + scale_color_manual(values='#D32F2F')
    if(i==2) plot.list[[i]] <- age.qq + scale_color_manual(values='#C2185B')
    if(i==3) plot.list[[i]] <- age.qq + scale_color_manual(values='#7B1FA2')
    if(i==4) plot.list[[i]] <- age.qq + scale_color_manual(values='#512DA8')
    if(i==5) plot.list[[i]] <- age.qq + scale_color_manual(values='#303F9F')
    if(i==6) plot.list[[i]] <- age.qq + scale_color_manual(values='#1976D2')
    if(i==7) plot.list[[i]] <- age.qq + scale_color_manual(values='#0288D1')
    if(i==8) plot.list[[i]] <- age.qq + scale_color_manual(values='#0097A7')
    if(i==9) plot.list[[i]] <- age.qq + scale_color_manual(values='#00796B')
    if(i==10) plot.list[[i]] <- age.qq + scale_color_manual(values='#388E3C')
    if(i==11) plot.list[[i]] <- age.qq + scale_color_manual(values='#689F38')
    if(i==12) plot.list[[i]] <- age.qq + scale_color_manual(values='#AFB42B')
    if(i==13) plot.list[[i]] <- age.qq + scale_color_manual(values='#FBC02D')
    if(i==14) plot.list[[i]] <- age.qq + scale_color_manual(values='#FFA000')
    
    #plot.list[[i]] <- age.qq + scale_color_manual(values=eval(as.character(color.vect[i])))
    i = i + 1
}
grid.arrange(plot.list[[1]], 
             plot.list[[2]],
             plot.list[[3]],
             plot.list[[4]],
             plot.list[[5]],
             plot.list[[6]],
             plot.list[[7]],
             plot.list[[8]],
             plot.list[[9]],
             plot.list[[10]],
             plot.list[[11]],
             plot.list[[12]],
             plot.list[[13]],
             plot.list[[14]], ncol=2)

Boxplots

After cleaning up the data and displaying it as a boxplot (below) we can better analyze the age and year variables. Each year is broken down and the data correlated with age to be displayed. Just by looking at the plots, we can see that while there is not a significant difference between the second and third quartiles between 1999 and 2012, it is clear the median age for runners in 2012 is lower than 1999. Also, a quick look at the boxplots shows the median age value appears to be gradually decreasing over time, with 2011 as the only exception. To verify this we took a closer look at the boxplot statistics, revealing the median age of runners in 1999 was 40, while the median age of runner in 2012 was 36. Another interesting metric is the number of observations also increased each year from 3189 in 1999 to 7191 in 2012. The data, as shown in the boxplot, does not have any significant outliers which leads to the conclusion the data is reliable, along with the distribution shown above. The boxplots help show a gradual decline in the age of runners over time.

bp.p <- ggplot(cbMensPlot, aes(x=year, y=age, fill=year)) + geom_boxplot() + theme(axis.text.x = element_text(angle = 45, hjust = 1)) + scale_y_continuous(breaks = pretty(cbMensPlot$age, n = 10))+
    stat_summary(fun.y=mean, geom="point", shape=5, size=4)
bp.p <- ggplotly(bp.p)
bp.p

Discussion and Future Works

In our initial analysis of age distribution across all years from 1999 to 2012, for the general population of male race runners, we find a right-skewed distribution with the highest frequency of runners falling into the 30-40 years age bin. Using a stacked density plot to show a single curve for each year, there is a notable decrease in mean age from 1999 to recent years and earlier years tend to have a much more normal distribution in age compared to recent years. Findings support original observations that age steadily decreases from a mean of 40.3352 to 37.7529 years. To that end, we speculate the decrease will slow moving forward, just as we have seen from 2008 to 2012. In addition, although mean distribution is shifting left, it is apparent that participation among age groups above 40 years has no significant decrease. Thus, we can see an increase in the rightly-skewed distribution for most recent years of the race.

Quantile-quantile plots are next used to assess normality of age distributions across years. A stacked (static) ggplot visual was produced, but proved too cumbersome to gleam insight from. We can see that several years have normality issues, but it is nearly impossible to understand which years the plot references. To mitigate these issues, we built a ggplot rendering of each year to assess individually before making comparisons. While no plots show perfect normality, we observe a trend in age distributions becoming less normal over time. Looking more closely at these ggplot visualizations, we see the strongest normality between 30-60 years of age in the 1999 race. As we move towards 2004 and more recent years, we observed a dip below the normality line and a larger variation under 30 years than was seen previously. We find the greatest variation from a normal distribution for the 2012 year. Overall, the quantile-quantile plot outcomes further support findings provided from density curves in that normality in age distributions is beginning to shift. We also note that in more recent years we begin to have a skewed distribution, likely caused by increased participation of younger individuals.

Lastly, boxplots are utilized to better analyze the age and year variables. The most apparent trend was that median age gradually decreases over time, excluding 2011. While no significant difference was seen between the second and third quartiles from 1999 to 2012, median age in 2012 is lower than 1999 (36 and 40, respectively). We also find that the number of observations increases year over year from 3,189 in 1999 to 7,191 in 2012. However, boxplot representations of the data show no significant outliers, providing strong evidence that the data was correctly formatted and is reliable. Therefore, final comparisons of age distribution across 14 years of the Cherry Blossom Ten Mile Run using density curves, quantile-quantile plots, and boxplots reveal an overall gradual decline in the age of runners over time. As an extension of this effort, future works would include modeling performance metrics and age distributions using different visualizations. We might consider evaluating age distribution across each year using residual plots or heat maps. Results would then be evaluated and compared against the density curves, quantile-quantile plots, and boxplots analyses to gain deeper insight and likely reinforce findings.

References

[1] D. Lang and D. Nolan, Data Science in R: A Case Studies Approach to Computation Reasoning and Problem Solving. New York, New York: CRC Press.

LS0tDQp0aXRsZTogIk1vZGVsaW5nIFJ1bm5lcnMnIFRpbWVzIGluIHRoZSBDaGVycnkgQmxvc3NvbSBSYWNlIC0gQ2FzZSBTdHVkeSBVbml0IDgiDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQNCiAgaHRtbF9kb2N1bWVudDogZGVmYXVsdA0KLS0tDQoNCiMjIyNDb3J5IEFkYW1zLCBDaHJpcyBCb29taG93ZXIsIEFsZXhhbmRyYSBGaXNoZXIsIEFsZXggRnJ5ZQ0KIyMjI01TRFMgNzMzMywgT2N0b2JlciAyNSwgMjAxNw0KDQoqKipOT1RFOiBBbnN3ZXJpbmcgUS4xMDogV2UgaGF2ZSBzZWVuIHRoYXQgdGhlIDE5OTkgcnVubmVycyB3ZXJlIHR5cGljYWxseSBvbGRlciB0aGFuIHRoZSAyMDEyIHJ1bm5lcnMuDQpDb21wYXJlIHRoZSBhZ2UgZGlzdHJpYnV0aW9uIG9mIHRoZSBydW5uZXJzIGFjcm9zcyBhbGwgMTQgeWVhcnMgb2YgdGhlIHJhY2VzLiBVc2UgcXVhbnRpbGUtDQpxdWFudGlsZSBwbG90cywgYm94cGxvdHMsIGFuZCBkZW5zaXR5IGN1cnZlcyB0byBtYWtlIHlvdXIgY29tcGFyaXNvbnMuIEhvdyBkbyB0aGUNCmRpc3RyaWJ1dGlvbnMgY2hhbmdlIG92ZXIgdGhlIHllYXJzPyBXYXMgaXQgYSBncmFkdWFsIGNoYW5nZT8qKioNCg0KIyNBYnN0cmFjdA0KSW4gdGhpcyBjYXNlIHN0dWR5LCByYWNlIHJlc3VsdHMgZm9yIHRoZSBDaGVycnkgQmxvc3NvbSBUZW4gTWlsZSBSdW4gZnJvbSAxOTk5IHRvIDIwMTIgYXJlIHVzZWQgdG8gc3R1ZHkgaG93IHBlb3BsZeKAmXMgcGh5c2ljYWwgcGVyZm9ybWFuY2UgY2hhbmdlcyB3aXRoIGFnZSBbMV0uIFRoZSBmb2N1cyBvZiB0aGUgc3R1ZHkgaW52b2x2ZXMgc2NyYXBpbmcgdGhlIFdlYiBmb3IgZnJlZSBhbmQgcHVibGljbHkgcHVibGlzaGVkIGRhdGEgYW5kIHRoZW4gZ2V0dGluZyB0aGF0IGRhdGEgaW50byB0aGUgY29ycmVjdCBmb3JtYXQuIEluIG9yZGVyIHRvIGludmVzdGlnYXRlIGhvdyBhZ2UgZGlzdHJpYnV0aW9ucyBjaGFuZ2Ugb3ZlciB0aGUgeWVhcnMsIGFnZSBkaXN0cmlidXRpb24gZm9yIGFsbCBydW5uZXJzIGFjcm9zcyAxNCB5ZWFycyBpcyBjb21wYXJlZDsgaG93ZXZlciwgd2hhdCBpbmZvcm1hdGlvbiBpcyByZWNvcmRlZCBhbmQgaG93IHRoZSBkYXRhIGlzIGZvcm1hdHRlZCBjaGFuZ2VzIGVhY2ggeWVhciBzbyBjbG9zZSBhdHRlbnRpb24gaXMgcGFpZCBmaXJzdCB0byBmb3JtYXR0aW5nIHRoZSBkYXRhLiBUaGUgUiBsYW5ndWFnZSBpcyBsZXZlcmFnZWQgdG8gYXBwcm9wcmlhdGVseSBmb3JtYXQgdGhlIGRhdGEgdmlhIHN0YXRpc3RpY2FsIGFuYWx5c2lzIGFuZCBleGFtaW5pbmcgc3VtbWFyeSBzdGF0aXN0aWNzIGFuZCBwbG90cy4gRm9sbG93aW5nIGRhdGEgYWNxdWlzaXRpb24gYW5kIHN1Y2Nlc3NmdWxseSByZWFkaW5nIHRhYmxlcyBvZiByYWNlIHJlc3VsdHMgaW50byBSLCByZXN1bHRzIGFyZSBhbmFseXplZCBhbmQgY29tcGFyZWQgdXNpbmcgZGVuc2l0eSBjdXJ2ZXMsIHF1YW50aWxlLXF1YW50aWxlIHBsb3RzLCBhbmQgYm94cGxvdHMuIEluIHRoaXMgd2F5LCB3ZSBhcmUgYWJsZSB0byB2aXN1YWxpemUgdGhlIGRhdGEgZm9yIHRlbnMgb2YgdGhvdXNhbmRzIG9mIG9ic2VydmF0aW9ucyB0byBleHBsb3JlIHRoZSBwZXJmb3JtYW5jZS1hZ2UgcmVsYXRpb25zaGlwIGFuZCB1bHRpbWF0ZWx5IGV4YW1pbmUgYWdlIGRpc3RyaWJ1dGlvbi4gRm9yIHRoZSBnZW5lcmFsIHBvcHVsYXRpb24gb2YgbWFsZSBydW5uZXJzLCB3ZSBmaW5kIGEgcmlnaHQtc2tld2VkIGRpc3RyaWJ1dGlvbiBpbiBhZ2Ugd2l0aCB0aGUgaGlnaGVzdCBmcmVxdWVuY3kgb2YgcnVubmVycyBmYWxsaW5nIGludG8gdGhlIDMwLTQwIHllYXIgYWdlIGJpbi4gRmluZGluZ3Mgc3VwcG9ydCBvcmlnaW5hbCBvYnNlcnZhdGlvbnMgdGhhdCBhZ2Ugc3RlYWRpbHkgZGVjcmVhc2VzIGluIGJvdGggbWVhbiBhbmQgbWVkaWFuIHZhbHVlcy4gRmluYWwgY29tcGFyaXNvbnMgb2YgYWdlIGRpc3RyaWJ1dGlvbiBhY3Jvc3MgYWxsIDE0IHllYXJzIHVzaW5nIGRlbnNpdHkgY3VydmVzLCBxdWFudGlsZS1xdWFudGlsZSBwbG90cywgYW5kIGJveHBsb3RzIGRlZmluaXRlbHkgcmV2ZWFsIGFuIG92ZXJhbGwgZ3JhZHVhbCBkZWNsaW5lIGluIHRoZSBhZ2Ugb2YgcnVubmVycyBvdmVyIHRpbWUuIEhvd2V2ZXIsIHdlIHNwZWN1bGF0ZSB0aGlzIGRlY2xpbmUgd2lsbCBzbG93IG1vdmluZyBpbnRvIHRoZSBmdXR1cmUganVzdCBhcyB3ZSBoYXZlIHNlZW4gZnJvbSAyMDA4IHRvIDIwMTIuDQoNCiMjSW50cm9kdWN0aW9uDQpUaGlzIGNhc2Ugc3R1ZHkgd2FzIHVuZGVydGFrZW4gaW4gb3JkZXIgdG8gZXhwbG9yZSBhbmQgc2hlZCBsaWdodCBvbiB0aGUgY29tcGxleCByZWxhdGlvbnNoaXAgYmV0d2VlbiBhIHBlcnNvbidzIGFnZSBhbmQgcGh5c2ljYWwgcGVyZm9ybWFuY2UuIERhdGEgdXNlZCBjb21lcyBmcm9tIHRoZSBpbmZhbW91cyBDcmVkaXQgVW5pb24gQ2hlcnJ5IEJsb3Nzb20gcmFjZS4gVGhlIENoZXJyeSBCbG9zc29tIFRlbiBNaWxlIFJ1biBpcyBoZWxkIGV2ZXJ5IHllYXIgZHVyaW5nIHRoZSBtb250aCBvZiBBcHJpbCBpbiBXYXNoaW5ndG9uLCBELkMuIHdoZW4gY2hlcnJ5IGJsb3Nzb20gdHJlZXMgYXJlIHNhaWQgdG8gYmxvb20uIFJhY2UgcmVzdWx0cyBmb3IgdGhlIENoZXJyeSBCbG9zc29tIFRlbiBNaWxlIFJ1biBhcmUgYXZhaWxhYmxlIHRvIHRoZSBwdWJsaWMgb25saW5lIGF0IGh0dHA6Ly93d3cuY2hlcnJ5Ymxvc3NvbS5vcmcvIGFuZCBjdXJyZW50bHkgaW5jbHVkZSBhbm51YWwgcmVzdWx0cyBzcGFubmluZyBmcm9tIDE5OTkgdG8gMjAxMiAoMTQgeWVhcnMgaW4gdG90YWwpLiBUaGUgcmFjZSBiZWdhbiBpbiAxOTczIGFuZCBoYXMgc2luY2UgZ3Jvd24gYnkgdGVucyBvZiB0aG91c2FuZHMgb2YgcnVubmVycyB0byAxNywwMDAgZW50cmllcyBpbiAyMDEyIHdpdGggYWdlcyByYW5naW5nIGZyb20gOSB0byA4OS4gSW4gZmFjdCwgdGhlIHJhY2UgaGFzIGJlZW4gaW4gc3VjaCBoaWdoIGRlbWFuZCB0aGF0IHJ1bm5lcnMgYXJlIGNob3NlbiB2aWEgYSBsb3R0ZXJ5IHN5c3RlbSB0byBlbnRlciB0aGUgcmFjZS4gQmVjYXVzZSBvZiB0aGUgZW5vcm1vdXMgYW1vdW50IG9mIG9ic2VydmF0aW9ucyB0aGVyZSBpcyBhIGNsZWFyIGFidW5kYW5jZSBvZiBpbmZvcm1hdGlvbiB0aGF0IGNhbiBiZSB1c2VkIGFzIGEgcmVzb3VyY2UgZm9yIGludmVzdGlnYXRpbmcgdGhlIHBlcmZvcm1hbmNlLWFnZSByZWxhdGlvbnNoaXAuDQoNClRvIHRoYXQgZW5kLCB3aGlsZSB0aGlzIGluZm9ybWF0aW9uIGlzIGZyZWUgYW5kIGF2YWlsYWJsZSB0byB0aGUgcHVibGljLCB3aGF0IGluZm9ybWF0aW9uIGlzIHJlcG9ydGVkIGFuZCBob3cgdGhlIGRhdGEgaXMgZm9ybWF0dGVkIGNoYW5nZXMgZWFjaCB5ZWFyLCBwcmVzZW50aW5nIGEgY2hhbGxlbmdlIHRoYXQgbXVzdCBmaXJzdCBiZSBvdmVyY29tZSBiZWZvcmUgY29uZHVjdGluZyBmdXJ0aGVyIGFuYWx5c2lzLiBUaGVyZWZvcmUsIGFmdGVyIGRhdGEgY2xlYW51cCBpcyBwZXJmb3JtZWQgYW5kIHJhY2UgcmVzdWx0cyBkYXRhIHRhYmxlcyBhcmUgcmVhZCBpbnRvIFIsIHdlIHRoZW4gdHVybiBvdXIgZm9jdXMgdG8gdGhlIGFnZSBkaXN0cmlidXRpb24gb2YgcnVubmVycyBhY3Jvc3MgYWxsIDE0IHllYXJzIG9mIHRoZSByYWNlcywgYXMgd2UgaGF2ZSBzZWVuIHRoYXQgdGhlIDE5OTkgcnVubmVycyB3ZXJlIHR5cGljYWxseSBvbGRlciB0aGFuIHRoZSAyMDEyIHJ1bm5lcnMgWzFdLiBUaGlzIGlzIGFjaGlldmVkIGJ5IGNyZWF0aW5nIHZpc3VhbCByZXByZXNlbnRhdGlvbnMgb2YgdGhlIGRhdGEgdGhyb3VnaCBkZW5zaXR5IGN1cnZlcywgcXVhbnRpbGUtcXVhbnRpbGUgcGxvdHMsIGFuZCBib3hwbG90cy4gVGhlc2UgdmlzdWFsaXphdGlvbnMgYXJlIGltcG9ydGFudCBmb3IgZ2FpbmluZyBkZWVwZXIgaW5zaWdodHMgYnkgc2VlaW5nIGhvdyBmYXN0IG9yIGdyYWR1YWwgY2hhbmdlcyBhcmUgb3ZlciB0aW1lLCBhcyB3ZWxsIGFzIGFueSBvdXRsaWVycyBvciBzdWJ0bGUgdHJlbmRzLiBGb3IgdGhlIHB1cnBvc2VzIG9mIHRoaXMgY2FzZSBzdHVkeSwgb25seSB0aGVzZSB0aHJlZSBjYXRlZ29yaWVzIG9mIHBsb3RzIGFyZSBjb25zaWRlcmVkIGZvciBvbmx5IG1hbGUgcnVubmVycyBhbmQgY29tcGFyZWQgZm9yIGEgZmluYWwgYW5hbHlzaXMgdG8gdWx0aW1hdGVseSBkZXRlcm1pbmUgaG93IHRoZSBkaXN0cmlidXRpb25zIGNoYW5nZSBvdmVyIHRoZSB5ZWFycyBhbmQgaWYgdGhlIGNoYW5nZXMgd2FzIGdyYWR1YWwuDQoNCiMjTWV0aG9kcw0KVGhlIHN0ZXBzIHVzZWQgZm9yIHRoaXMgYW5hbHlzaXMgd2VyZTogMSkgZGF0YSBhY3F1aXNpdGlvbjsgMikgYWRkaXRpb25hbCBkYXRhIGNsZWFudXAgZm9yIG91dGxpZXIgcmVtb3ZhbDsgMykgZGVuc2l0eSBjdXJ2ZXMgYW5hbHlzaXM7IDQpIHF1YW50aWxlLXF1YW50aWxlIHBsb3RzIGFuYWx5c2lzOyBhbmQgNSkgYm94cGxvdHMgYW5hbHlzaXMuDQoNCipOb3RlIHRoYXQgY29kZSB1c2VkIGluY2x1ZGVzIG1vZGlmaWVkIHZlcnNpb25zIG9mIFIgY29kZSBmdW5jdGlvbiBleGFtcGxlcyBmb3VuZCBpbiBEYXRhIFNjaWVuY2UgaW4gUjogQSBDYXNlIFN0dWRpZXMgQXBwcm9hY2ggdG8gQ29tcHV0YXRpb25hbCBSZWFzb25pbmcgYW5kIFByb2JsZW0gU29sdmluZywgQ2hhcHRlciAyLCBwYWdlcyA0Ny0xMDAgWzFdLioNCg0KIyNSZXN1bHRzDQoNCiMjIyNEYXRhIEFjcXVpc2l0aW9uDQpUbyBiZWdpbiwgd2UgdXRpbGl6ZWQgbWV0aG9kcyBwcm92aWRlZCBpbiB0aGUgRGF0YSBTY2llbmNlIGluIFIgdGV4dCB0byBsb2FkIG1hbGUgcnVubmVycyBmcm9tIDE5OTkgdG8gMjAxMi4gQXMgdGhlIHB1cnBvc2Ugb2YgdGhpcyBhbmFseXNpcyBpcyB0byByZXNlYXJjaCB0aGlzIGRhdGEgcG9zdCBsb2FkLCB3ZSBoYXZlIGV4Y2x1ZGVkIHRoZSBzY3JhcGluZyBwcm9jZXNzIGZyb20gdGhpcyBhbmFseXNpcyBhbmQgdGhlIGRhdGEgaXMgbG9hZGVkIGV4dGVybmFsIHRvIHRoZSBub3RlYm9vayBpbiB0aGUgYGBgRGF0YUV4dHJhY3RBbmRDbGVhbi5SYGBgIGZpbGUgYWxsb3dpbmcgdXMgdG8gZm9jdXMgb24gb3VyIGFuYWx5c2lzIG9mIGFnZSBkaXN0cmlidXRpb25zLg0KYGBge3IgaW5jbHVkZT1GQUxTRSwgY2FjaGU9VFJVRX0NCnNvdXJjZSgnRGF0YUV4dHJhY3RBbmRDbGVhbi5SJywgZWNobyA9IEZBTFNFKQ0KYGBgDQoNCg0KYGBge3IgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZyA9IEZBTFNFfQ0KIyMjI0xvYWQgTGlicmFyaWVzDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KHBsb3RseSkNCmxpYnJhcnkocGx5cikNCmxpYnJhcnkoZ3JpZCkNCmxpYnJhcnkoZ3JpZEV4dHJhKQ0KbGlicmFyeShmb3JtYXR0YWJsZSkNCmBgYA0KDQojIyMjRGF0YSBDbGVhbnVwIGZvciBPdXRsaWVyIFJlbW92YWwNCmBgYHtyIGVjaG8gPSAiZmFsc2UifQ0KbGVuTFJUPC1ucm93KGNiTWVuW2NiTWVuJHJ1blRpbWUgPCAzMCwgXSkNCmxlbk5BQUc8LW5yb3coY2JNZW5baXMubmEoY2JNZW4kYWdlKSwgXSkNCmxlbkxBRzwtbnJvdyhjYk1lbltjYk1lbiRhZ2UgPCAxMCAmICFpcy5uYShjYk1lbiRhZ2UpLCBdKQ0KbGVuVG90RGlydHk8LW5yb3coY2JNZW4pDQpsZW5Ub3RDbGVhbjwtbnJvdyhjYk1lbltjYk1lbiRydW5UaW1lID4gMzAgJiAhaXMubmEoY2JNZW4kYWdlKSAmIGNiTWVuJGFnZSA+PSAxMCwgXSkNCmBgYA0KDQpCZWZvcmUgYmVnaW5uaW5nIG91ciBhbmFseXNpcyBvZiBhZ2UgZGlzdHJpYnV0aW9ucywgd2UgaGF2ZSBzb21lIHByZWxpbWluYXJ5IGRhdGEgY2xlYW51cCB0byBwZXJmb3JtIG9uIG11bHRpcGxlIHNjZW5hcmlvcywgYXMgdGhpcyBhbmFseXNpcyBpcyBtZWFudCB0byByZXByZXNlbnQgdGhlIGdlbmVyYWwgcG9wdWxhdGlvbiBsZXNzIG91dGxpZXJzLiBGaXJzdCwgdGhlcmUgaXMgYGBgYHIgbGVuTFJUYGBgYCBvYnNlcnZhdGlvbiB3aGljaCBhcHBlYXJzIHRvIGNvbnRhaW4gYW4gb3V0bGllciBmb3IgaXRzIHJ1bi10aW1lOyBhIDcwIHllYXIgb2xkIHdpdGggYSBydW4tdGltZSBvZiAxLjUgd2hpY2ggaXMgbGlrZWx5IGVpdGhlciBkdWUgdG8gYSBub24tc3RhcnRlciBvciBhIGRhdGEgZW50cnkgZXJyb3IuIA0KDQpgYGB7ciBlY2hvID0gImZhbHNlIn0NCmZvcm1hdHRhYmxlKGNiTWVuW2NiTWVuJHJ1blRpbWUgPCAzMCwgXSkNCmBgYA0KDQpTZWNvbmQsIHdlIGlkZW50aWZ5IGBgYGByIGxlbk5BQUdgYGBgIG9ic2VydmF0aW9ucyB3aGljaCBoYXZlIG51bGwgdmFsdWVzIGZvciBhZ2UuIFRoZXNlIHJlY29yZHMgYXJlIHVuYWJsZSB0byBiZSB2aXN1YWxpemVkIGZvciBhZ2UgZGlzdHJpYnV0aW9ucywgYW5kIHRodXMgcmVtb3ZlZCBhcyB3ZWxsLiANCg0KYGBge3IgZWNobyA9ICJmYWxzZSJ9DQpmb3JtYXR0YWJsZShjYk1lbltpcy5uYShjYk1lbiRhZ2UpLCBdKQ0KYGBgDQoNCkxhc3RseSwgd2UgaWRlbnRpZnkgYGBgYHIgbGVuTEFHYGBgYCBvYnNlcnZhdGlvbnMgd2l0aCBhbiBhZ2UgbGVzcyB0aGFuIDEwLiBBbHRob3VnaCB0aGVyZSBjb3VsZCBiZSBhIHlvdW5nIGNoaWxkIGluIHRoZSBydW4sICB0aGVyZSBhcmUgc2V2ZXJhbCBvZiB0aGVzZSB2YWx1ZXMgd2l0aCBhbiBhZ2UgYmV0d2VlbiAwIGFuZCA0LCBsZWF2aW5nIHVzIHVudHJ1c3Rpbmcgb2YgdGhlIG90aGVyIHRocmVlIHZhbHVlcyByZW1haW5pbmcgZm9yIDggYW5kIDkgeWVhciBvbGRzLiBEdWUgdG8gdGhpcywgd2UgaGF2ZSBkZWNpZGUgdG8gY3V0IG9mZiB0aGUgYWdlIGxvd2VyIGxpbWl0IGF0IDEwIHllYXJzIG9sZCB0byBkZXNjcmliZSBnZW5lcmFsIHBvcHVsYXRpb24uIA0KDQpgYGB7ciBlY2hvID0gImZhbHNlIn0NCmZvcm1hdHRhYmxlKGNiTWVuW2NiTWVuJGFnZSA8IDEwICYgIWlzLm5hKGNiTWVuJGFnZSksIF0pDQpgYGANCg0KYGBge3J9DQpjYk1lblN1YiA9IGNiTWVuW2NiTWVuJHJ1blRpbWUgPiAzMCAmICFpcy5uYShjYk1lbiRhZ2UpICYgY2JNZW4kYWdlID49IDEwLCBdDQpgYGANCg0KV2l0aCB0aGVzZSBmZXcgb3V0bGllcnMgcmVtb3ZlZCwgd2UgdHJhbnNmb3JtIGZyb20gYGBgYHIgbGVuVG90RGlydHlgYGBgIHRvIGBgYGByIGxlblRvdENsZWFuYGBgYCBvYnNlcnZhdGlvbnMuIFdlIGFyZSBub3cgcmVhZHkgdG8gbW92ZSBmb3J3YXJkIHdpdGggb3VyIGFuYWx5c2lzIG9mIGFnZSBkaXN0cmlidXRpb25zIGFtb25nc3QgZWFjaCB5ZWFyLg0KDQojIyMjRGVuc2l0eSBDdXJ2ZQ0KYGBge3IgZWNobyA9ICJmYWxzZSJ9DQptZWFuQWdlQWxsWXJzIDwtIG1lYW4oY2JNZW5TdWIkYWdlKQ0KTWVkaWFuQWdlQWxsWXJzIDwtIG1lZGlhbihjYk1lblN1YiRhZ2UpDQpNZWFuMTk5OUFnZSA8LW1lYW4oY2JNZW5TdWJbY2JNZW5TdWIkeWVhcj09MTk5OSwiYWdlIl0pDQpNZWFuMjAwNEFnZSA8LW1lYW4oY2JNZW5TdWJbY2JNZW5TdWIkeWVhcj09MjAwNCwiYWdlIl0pDQpNZWFuMjAwOEFnZSA8LW1lYW4oY2JNZW5TdWJbY2JNZW5TdWIkeWVhcj09MjAwOCwiYWdlIl0pDQpNZWFuMjAxMkFnZSA8LW1lYW4oY2JNZW5TdWJbY2JNZW5TdWIkeWVhcj09MjAxMiwiYWdlIl0pDQpgYGANClRvIGJlZ2luIG91ciBkZW5zaXR5IGN1cnZlIGFuYWx5c2lzLCB3ZSBmaXJzdCB3ZXJlIGludGVyZXN0ZWQgaW4gdGhlIG92ZXJhbGwgZGlzdHJpYnV0aW9uIG9mIGFnZSBpbiB0aGUgcG9wdWxhdGlvbiBhY3Jvc3MgYWxsIHllYXJzLiBBY3Jvc3MgYWxsIDE0IHllYXJzLCB0aGUgbWVhbiBhZ2UgaXMgYGBgYHIgbWVhbkFnZUFsbFlyc2BgYGAsIHdoZXJlYXMgdGhlIG1lZGlhbiBhZ2UgaXMgYGBgYHIgTWVkaWFuQWdlQWxsWXJzYGBgYC4gVGhpcyBzdWdnZXN0cywgc2luY2UgdGhlIG1lYW4gdmFsdWUgaXMgbGFyZ2VyIHRoYW4gdGhlIG1lZGlhbiwgdGhhdCB3ZSBoYXZlIGEgc2xpZ2h0bHkgcmlnaHQtc2tld2VkIGRpc3RyaWJ1dGlvbi4gQnJlYWtpbmcgYWdlIGludG8gYmlucyBvZiBkZWNhZGUgZ3JvdXBzICgxMC0yMCwgMjAtMzAsLi4uLDcwLDgwLCBldGMuKSwgd2UgYXJlIGFibGUgdG8gdmlzdWFsaXplIHRoZSBvdmVyYWxsIGRpc3RyaWJ1dGlvbiBvZiBhZ2UuIFRoZXNlIGJpbiBjb3VudHMgaGVscCBmdXJ0aGVyIHRoZXNlIGZpbmRpbmdzLCB3aXRoIG91ciBtb3N0IGZyZXF1ZW5jeSBiaW4gaW5jbHVkaW5nIGFnZXMgMzAtNDAsIHRoZSBzYW1lIGlkZW50aWZpZWQgZm9yIG1lYW4gYW5kIG1lZGlhbiBhZ2UuIFRoZSBkaXN0cmlidXRpb24gb2YgYmluIGNvdW50cyBhbHNvIGZ1cnRoZXIgc3VwcG9ydHMgdGhlIHJpZ2h0LXNrZXcgZGlzdHJpYnV0aW9uIGFzIHRoZXJlIGlzIGEgc2xpZ2h0bHkgbG9uZ2VyIHRhaWwgZnJvbSA0MC05MCBpbiBjb21wYXJpc29uIHRvIHRoYXQgYmV0d2VlbiAxMC0zMC4NCg0KYGBge3J9DQphZ2VDYXQgPSBjdXQoY2JNZW5TdWIkYWdlLCBicmVha3MgPSBjKHNlcSgxMCwgODAsIDEwKSwgOTApKQ0KYmlucz1hcy5kYXRhLmZyYW1lKHRhYmxlKGFnZUNhdCkpDQoNCmJpbnMucCA8LWdncGxvdChiaW5zLCBhZXMoeD1hZ2VDYXQsIHk9RnJlcSkpICsgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKQ0KYmlucy5wPC1nZ3Bsb3RseShiaW5zLnApDQpiaW5zLnANCmBgYA0KDQpUbyBmdXJ0aGVyIHRoaXMgYW5hbHlzaXMsIHdlIGFyZSBpbnRlcmVzdGVkIHRvIHNlZSBob3cgYWdlIGRpc3RyaWJ1dGlvbiBoYXMgY2hhbmdlZCBvdmVyIHRoZSBtYW55IHllYXJzIHRoaXMgcmFjZSBoYXMgYmVlbiBjb25kdWN0ZWQuIEJlbG93IGlzIGEgc3RhY2tlZCBkZW5zaXR5IHBsb3QsIHByb3ZpZGluZyBhIHNpbmdsZSBjdXJ2ZSBmb3IgZXZlcnkgeWVhci4gTm90ZXdvcnRoeSB0byBtZW50aW9uLCB0aGUgcGxvdCBwcm92aWRlZCBpcyByZW5kZXJlZCB3aXRoIHBsb3RseSwgYWxsb3dpbmcgaW50ZXJhY3RpdmUgaG92ZXIgdmFsdWVzLCB6b29tIGNvbnRyb2xzLCBhbmQgdG9nZ2xpbmcgb2YgeWVhcnMgdG8gZGlzcGxheSBieSBjbGlja2luZyBvbiB0aGUgbGVnZW5kLiBCZWZvcmUgdGFyZ2V0dGluZyBzcGVjaWZpYyB5ZWFycywgdGhlcmUgYXBwZWFycyB0byBiZSBhIG5vdGFibGUgZGVjcmVhc2UgaW4gbWVhbiBhZ2UgZnJvbSAxOTk5IHRvIHJlY2VudCB5ZWFycy4gQWRkaXRpb25hbGx5LCBlYXJsaWVyIHllYXJzIGFwcGVhciB0byBoYXZlIGEgbXVjaCBtb3JlIG5vcm1hbCBkaXN0cmlidXRpb24gaW4gYWdlIHRoYW4gdGhhdCBvZiByZWNlbnQgeWVhcnMuDQoNCkJ5IGNsaWNraW5nIG9uIGluZGl2aWR1YWwgbGVnZW5kIHllYXJzIHsxOTk5LCAyMDA0LCAyMDA4LCAyMDEyfSwgd2UgbWF5IGRlLWNsdXR0ZXIgdGhlIHZpc3VhbCBmb3IgZnVydGhlciByZXNlYXJjaCBpbnRvIHRoZXNlIGZpbmRpbmdzIG9uIGEgd2lkZSBzcHJlYWQgb2YgeWVhciBydW5zLiBUaGUgbWVhbiBhZ2UgbWF5IGJlIHNlZW4gaW4gdGhlIHRhYmxlIGJlbG93LiANCg0KfCAgWWVhciAgfCAgICAgTWVhbiBBZ2UgICAgICAgICAgfA0KfDotLS0tLS06fDotLS0tLS0tLS0tLS0tLS0tLS0tLS06fA0KfCoqMTk5OSoqfCBgYGBgciBNZWFuMTk5OUFnZWBgYGAgfA0KfCoqMjAwNCoqfCBgYGBgciBNZWFuMjAwNEFnZWBgYGAgfA0KfCoqMjAwOCoqfCBgYGBgciBNZWFuMjAwOEFnZWBgYGAgfA0KfCoqMjAxMioqfCBgYGBgciBNZWFuMjAxMkFnZWBgYGAgfA0KDQpBcyB3YXMgb3JpZ2luYWxseSBnbGVhbWVkLCBhZ2VzIHN0ZWFkaWx5IGRlY3JlYXNlIGZyb20gYSBtZWFuIG9mIGBgYHIgTWVhbjE5OTlBZ2VgYGAgdG8gYGBgciBNZWFuMjAxMkFnZWBgYCB5ZWFycyBvbGQuIGFzIHRoZSBkZW5zaXR5IGN1cnZlcyBhbHNvIHN1Z2dlc3QsIHdlIG9ic2VydmUgdGhlIGN1cnZlcyBzaGlmdCBwb3NpdGlvbnMgZnJvbSByaWdodCB0byBsZWZ0IGFuZCBkZW5zaXR5IHNrZXduZXNzIGVsb25nYXRlIGFzIHdlIHByb2dyZXNzIGZyb20gZWFybHkgdG8gcmVjZW50IHllYXJzLiBUaGVzZSBmaW5kaW5ncyBjb25maXJtIG91ciBvcmlnaW5hbCBvYnNlcnZhdGlvbnMsIGluZGljYXRpbmcgdGhhdCB0aGUgY29yZSBkZW1vZ3JhcGhpYyBmb3IgcGFydGljaXBhdGluZyBydW5uZXJzIGFyZSBkZWNyZWFzaW5nIHllYXIgYWZ0ZXIgeWVhci4gV2Ugc3BlY3VsYXRlIHRoaXMgZGVjcmVhc2Ugd2lsbCBzbG93IGRvd24gbW92aW5nIGZvcndhcmQsIGp1c3QgYXMgd2FzIHNlZW4gZnJvbSAyMDA4IHRvIDIwMTIsIHdpdGggb25seSBhIGBgYHIgTWVhbjIwMDhBZ2UtTWVhbjIwMTJBZ2VgYGAgZGlmZmVyZW5jZSBpbiBtZWFuIGFnZSBpbiB0aG9zZSB5ZWFycyBzaW5jZSBwYXJ0aWNpcGFudHMgdW5kZXIgMjAgaGF2ZSBiZWVuIGluc2lnbmlmaWNhbnQgYWNyb3NzIGFsbCB5ZWFycyBvZiB0aGUgcmFjZS4gQWx0aG91Z2ggdGhlIG1lYW4gZGlzdHJpYnV0aW9uIGlzIHNoaWZ0aW5nIGxlZnQsIGl0IGlzIGFwcGFyZW50IHRoYXQgcGFydGljaXBhdGlvbiBhbW9uZ3N0IHRoZSBhZ2UgZ3JvdXBzIGFib3ZlIDQwIGhhdmUgbm90IHNpZ25pZmljYW50bHkgZGVjcmVhc2VkLiBCZWNhdXNlIG9mIHRoaXMsIHdlIGJlZ2luIHNlZWluZyB0aGUgcmlnaHQtc2tldyBkaXN0cmlidXRpb24gaW5jcmVhc2UgaW4gdGhlIG1vc3QgcmVjZW50IHllYXJzIG9mIHRoZSByYWNlLg0KDQpgYGB7cn0NCiMgU3Vic2V0IGluIG9yZGVyIHRvIGNvbG9yIGJ5IHllYXINCmNiTWVuc1Bsb3QgPC0gY2JNZW5TdWINCmNiTWVuc1Bsb3QkeWVhciA8LSBhcy5jaGFyYWN0ZXIoY2JNZW5zUGxvdCR5ZWFyKQ0KDQoNCmFnZS5kID0gZ2dwbG90KGNiTWVuc1Bsb3QsIGFlcyhhZ2UsIGNvbG9yID0geWVhcikpICsgZ2VvbV9kZW5zaXR5KCkgKyBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gcHJldHR5KGNiTWVuc1Bsb3QkYWdlLCBuID0gMTApKQ0KYWdlLmQgPSBnZ3Bsb3RseShhZ2UuZCkgI0NvbnZlcnQgdG8gcGxvdGx5IHZlcnNpb24NCmFnZS5kDQpgYGANCg0KIyMjI1F1YW50aWxlLVF1YW50aWxlIFBsb3RzDQpOZXh0IGluIG91ciBhbmFseXNpcywgd2UgYXJlIGludGVyZXN0ZWQgdG8gZnVydGhlciBidWlsZCBvdXIgY2FzZSBvbiBub3JtYWxpdHkgb2YgYWdlIGRpc3RyaWJ1dGlvbnMgYWNyb3NzIHRoZSBtYW55IHllYXJzIG9mIHRoZSByYWNlLiBUbyBkbyB0aGlzLCB3ZSBkZWNpZGUgdG8gcHJvZHVjZSBhIFF1YW50aWxlLVF1YW50aWxlIFBsb3QgKFFRUGxvdCkgdG8gYXNzZXNzIG91ciBkYXRhJ3MgcXVhbnRpbGVzIGFnYWluc3QgYSB0aGVvcmV0aWNhbCBub3JtYWwgZGlzdHJpYnV0aW9uIHF1YW50aWxlLiBJZiBvdXIgZGF0YSBwb3NlcyBhcyBwZXJmZWN0bHkgbm9ybWFsLCB3ZSB3b3VsZCBzZWUgYSBzdHJhaWdodCBsaW5lLiBUaGUgbW9yZSBvdXIgc2NhdHRlciB2YXJpZXMgZnJvbSB0aGUgaWRlYWwgbGluZSwgdGhlIGZ1cnRoZXIgZnJvbSBub3JtYWxpdHkgaXMgdGhlIGRpc3RyaWJ1dGlvbi4NCg0KSW4gZWZmb3J0cyB0byBjcmVhdGUgYW4gaW50ZXJhY3RpdmUgcGxvdGx5IHZpc3VhbGl6YXRpb24gZm9yIHRoZXNlIFFRUGxvdHMgYXMgd2FzIGRvbmUgZm9yIGRlbnNpdHkgY3VydmVzLCB0aGUgcmVuZGVyaW5nIHdhcyBvdmVyYmVhcmluZyBpbiB0ZXJtcyBvZiBwZXJmb3JtYW5jZS4gRHVlIHRvIHRoZXNlIGlzc3VlcywgdGhlIHN0YWNrZWQgKHN0YXRpYykgZ2dwbG90IHZpc3VhbCBpcyBwcm92aWRlZCwgaG93ZXZlciB2ZXJ5IGRpZmZpY3VsdCB0byBnbGVhbSBpbnNpZ2h0cyBmcm9tLiBJdCBpcyBhcHBhcmVudCB0aGF0IHNldmVyYWwgb2YgdGhlc2UgeWVhcnMgaGF2ZSBub3JtYWxpdHkgcHJvYmxlbXMsIGhvd2V2ZXIgdmVyeSBkaWZmaWN1bHQgdG8gdW5kZXJzdGFuZCB3aGljaCB5ZWFycyB0aGUgcGxvdCByZWZlcmVuY2VzLiANCmBgYHtyfQ0KIyBjYWxjdWxhdGUgdGhlIG5vcm1hbCB0aGVvcmV0aWNhbCBxdWFudGlsZXMgcGVyIGdyb3VwDQpjYk1lbnNQbG90UVEgPC0gZGRwbHkoLmRhdGEgPSBjYk1lbnNQbG90LCAudmFyaWFibGVzID0gLih5ZWFyKSwNCiAgICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbihkc3ViKXsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgcSA8LSBxcW5vcm0oZHN1YiRhZ2UsIHBsb3QgPSBGQUxTRSkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgZHN1YiR4cSA8LSBxJHgNCiAgICAgICAgICAgICAgICAgICAgICAgICAgZHN1Yg0KICAgICAgICAgICAgICAgICAgICAgIH0pDQoNCmFnZS5xcSA9IGdncGxvdChkYXRhID0gY2JNZW5zUGxvdFFRLCBhZXMoeCA9IHhxLCB5ID0gYWdlLCBjb2xvciA9IHllYXIpKSArDQogICAgICAgICAgICAgICAgZ2VvbV9wb2ludCgpICsNCiAgICAgICAgICAgICAgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFKSArDQogICAgICAgICAgICAgICAgeGxhYigiTm9ybWFsIFRoZW9yZXRpY2FsIFF1YW50aWxlcyIpICsNCiAgICAgICAgICAgICAgICB5bGFiKCJOb3JtYWwgRGF0YSBRdWFudGlsZXMiKQ0KI2FnZS5xcSA9IGdncGxvdGx5KGFnZS5xcSkNCmFnZS5xcQ0KYGBgDQoNClRvIG1pdGlnYXRlIHRoZXNlIGlzc3Vlcywgd2UgYnVpbGQgZ2dwbG90IHJlbmRlcmluZyBvZiBlYWNoIHllYXIgaW5kaXZpZHVhbGx5IGJlbG93IGluIG9yZGVyIHRvIGFzc2VzcyBpbmRpdmlkdWFsbHkgaW4gY29tcGFyaXNvbiB0byB0aGUgb3RoZXJzLiBBbHRob3VnaCBub25lIG9mIHRoZXNlIHBsb3RzIHByb3ZpZGUgdXMgd2l0aCBhICJwZXJmZWN0IiBsaW5lIHJlcHJlc2VudGluZyBub3JtYWxpdHksIHdlIGNhbiBhc3NlcnQgdGhhdCBvdmVyIHRpbWUgdGhlIGRpc3RyaWJ1dGlvbnMgZm9yIGFnZSBiZWNvbWUgbGVzcyBub3JtYWwuIExvb2tpbmcgYXQgdGhlIHNhbWUgeWVhcnMgezE5OTksMjAwNCwgMjAwOCwgMjAxMn0gYXMgd2FzIGRvbmUgcHJldmlvdXNseSwgd2Ugc2VlIHZlcnkgc3Ryb25nIG5vcm1hbGl0eSBiZXR3ZWVuIH4zMC02MCB5ZWFycyBvZiBhZ2UgaW4gdGhlIDE5OTkgcmFjZS4gTW92aW5nIHRvd2FyZHMgMjAwNCwgd2UgYmVnaW4gdG8gc2VlIHRoZSBzY2F0dGVyIGRpcCBiZWxvdyB0aGUgbm9ybWFsaXR5IGxpbmUsIGFuZCBhIGxhcmdlciB2YXJpYXRpb24gdW5kZXIgMzAgdGhhbiB3YXMgc2VlbiBiZWZvcmUuIEluIDIwMDgsIHdlIG9uY2UgYWdhaW4gc2VlIHRoZSBzY2F0dGVyIGRyb3BwaW5nIGJlbG93IHRoZSBub3JtYWxpdHkgbGluZSwgYW5kIGluY3JlYXNpbmcgdmFyaWFuY2UgaW4gYm90aCBhZ2VzIHVuZGVyIDMwIGFuZCB0aG9zZSBhYm92ZSA1MCB5ZWFycyBvbGQuIEZpbmFsbHksIGluIDIwMTIsIHdlIHNlZSB2YXJpYXRpb24gYW1vbmdzdCB0aGUgbWFqb3JpdHkgb2YgdGhlIHNjYXR0ZXIgYW5kIHRoZSBub3JtYWxpdHkgbGluZS4gVGhlc2UgcmVzdWx0cyBoZWxwIHRvIGZ1cnRoZXIgc3VwcG9ydCB0aG9zZSBmaW5kaW5ncyBwcm92aWRlZCBmcm9tIGRlbnNpdHkgY3VydmVzLCBpbiB0aGF0IG5vcm1hbGl0eSBpbiBhZ2UgZGlzdHJpYnV0aW9ucyBoYXMgYmVnYW4gdG8gc2hpZnQuIEluIHJlY2VudCB5ZWFycywgd2UgYmVnaW4gdG8gaGF2ZSBhIHNrZXdlZCBkaXN0cmlidXRpb24sIGxpa2VseSBjYXVzZWQgYnkgdGhlIGluY3JlYXNlZCBwYXJ0aWNpcGF0aW9uIG9mIHRoZSB5b3VuZ2VyIGluZGl2aWR1YWxzLiANCmBgYHtyIGZpZy53aWR0aD0xMiwgZmlnLmFzcD0xLjV9DQoNCnBsb3QubGlzdCA8LSBsaXN0KCkNCmkgPSAxDQojY29sb3IudmVjdCA8LSBjKCcjRDMyRjJGJywgJyNDMjE4NUInLCAnIzdCMUZBMicsICcjNTEyREE4JywgJyMzMDNGOUYnLCAnIzE5NzZEMicsICcjMDI4OEQxJywNCiMgICAgICAgICAgICAgICAgJyMwMDk3QTcnLCAnIzAwNzk2QicsICcjMzg4RTNDJywgJyM2ODlGMzgnLCAnI0FGQjQyQicsICcjRkJDMDJEJywgJyNGRkEwMDAnKQ0KDQpmb3IoeXIgaW4gdW5pcXVlKGNiTWVuc1Bsb3QkeWVhcikpew0KICAgIGNiTWVuc1Bsb3RRUSA8LSBkZHBseSguZGF0YSA9IHN1YnNldChjYk1lbnNQbG90LCBjYk1lbnNQbG90JHllYXIgPT0geXIpLCAudmFyaWFibGVzID0gLih5ZWFyKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24oZHN1Yil7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBxIDwtIHFxbm9ybShkc3ViJGFnZSwgcGxvdCA9IEZBTFNFKQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZHN1YiR4cSA8LSBxJHgNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRzdWINCiAgICAgICAgICAgICAgICAgICAgICAgICAgfSkNCiAgICANCiAgICBhZ2UucXEgPSBnZ3Bsb3QoZGF0YSA9IGNiTWVuc1Bsb3RRUSwgYWVzKHggPSB4cSwgeSA9IGFnZSwgY29sb3IgPSB5ZWFyKSkgKw0KICAgICAgICAgICAgICAgICAgICBnZW9tX3BvaW50KCkgKw0KICAgICAgICAgICAgICAgICAgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFKSArDQogICAgICAgICAgICAgICAgICAgIHhsYWIoIk5vcm1hbCBUaGVvcmV0aWNhbCBRdWFudGlsZXMiKSArDQogICAgICAgICAgICAgICAgICAgIHlsYWIoIk5vcm1hbCBEYXRhIFF1YW50aWxlcyIpDQogICAgDQogICAgI2dncGxvdCBkb2Vzbid0IGxpa2UgdG8gZXZhbHVhdGUgdmVjdG9yIGluZGV4ZWQgY29udGVudHMgc28gaGF2aW5nIHRvIGV4cGxpY2l0bHkgd3JpdGUgY29sb3IgdmFsdWVzIGxpbmUtYnktbGluZQ0KICAgIGlmKGk9PTEpIHBsb3QubGlzdFtbaV1dIDwtIGFnZS5xcSArIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9JyNEMzJGMkYnKQ0KICAgIGlmKGk9PTIpIHBsb3QubGlzdFtbaV1dIDwtIGFnZS5xcSArIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9JyNDMjE4NUInKQ0KICAgIGlmKGk9PTMpIHBsb3QubGlzdFtbaV1dIDwtIGFnZS5xcSArIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9JyM3QjFGQTInKQ0KICAgIGlmKGk9PTQpIHBsb3QubGlzdFtbaV1dIDwtIGFnZS5xcSArIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9JyM1MTJEQTgnKQ0KICAgIGlmKGk9PTUpIHBsb3QubGlzdFtbaV1dIDwtIGFnZS5xcSArIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9JyMzMDNGOUYnKQ0KICAgIGlmKGk9PTYpIHBsb3QubGlzdFtbaV1dIDwtIGFnZS5xcSArIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9JyMxOTc2RDInKQ0KICAgIGlmKGk9PTcpIHBsb3QubGlzdFtbaV1dIDwtIGFnZS5xcSArIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9JyMwMjg4RDEnKQ0KICAgIGlmKGk9PTgpIHBsb3QubGlzdFtbaV1dIDwtIGFnZS5xcSArIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9JyMwMDk3QTcnKQ0KICAgIGlmKGk9PTkpIHBsb3QubGlzdFtbaV1dIDwtIGFnZS5xcSArIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9JyMwMDc5NkInKQ0KICAgIGlmKGk9PTEwKSBwbG90Lmxpc3RbW2ldXSA8LSBhZ2UucXEgKyBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPScjMzg4RTNDJykNCiAgICBpZihpPT0xMSkgcGxvdC5saXN0W1tpXV0gPC0gYWdlLnFxICsgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz0nIzY4OUYzOCcpDQogICAgaWYoaT09MTIpIHBsb3QubGlzdFtbaV1dIDwtIGFnZS5xcSArIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9JyNBRkI0MkInKQ0KICAgIGlmKGk9PTEzKSBwbG90Lmxpc3RbW2ldXSA8LSBhZ2UucXEgKyBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPScjRkJDMDJEJykNCiAgICBpZihpPT0xNCkgcGxvdC5saXN0W1tpXV0gPC0gYWdlLnFxICsgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz0nI0ZGQTAwMCcpDQogICAgDQogICAgI3Bsb3QubGlzdFtbaV1dIDwtIGFnZS5xcSArIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9ZXZhbChhcy5jaGFyYWN0ZXIoY29sb3IudmVjdFtpXSkpKQ0KICAgIGkgPSBpICsgMQ0KfQ0KDQpncmlkLmFycmFuZ2UocGxvdC5saXN0W1sxXV0sIA0KICAgICAgICAgICAgIHBsb3QubGlzdFtbMl1dLA0KICAgICAgICAgICAgIHBsb3QubGlzdFtbM11dLA0KICAgICAgICAgICAgIHBsb3QubGlzdFtbNF1dLA0KICAgICAgICAgICAgIHBsb3QubGlzdFtbNV1dLA0KICAgICAgICAgICAgIHBsb3QubGlzdFtbNl1dLA0KICAgICAgICAgICAgIHBsb3QubGlzdFtbN11dLA0KICAgICAgICAgICAgIHBsb3QubGlzdFtbOF1dLA0KICAgICAgICAgICAgIHBsb3QubGlzdFtbOV1dLA0KICAgICAgICAgICAgIHBsb3QubGlzdFtbMTBdXSwNCiAgICAgICAgICAgICBwbG90Lmxpc3RbWzExXV0sDQogICAgICAgICAgICAgcGxvdC5saXN0W1sxMl1dLA0KICAgICAgICAgICAgIHBsb3QubGlzdFtbMTNdXSwNCiAgICAgICAgICAgICBwbG90Lmxpc3RbWzE0XV0sIG5jb2w9MikNCmBgYA0KDQojIyMjQm94cGxvdHMNCkFmdGVyIGNsZWFuaW5nIHVwIHRoZSBkYXRhIGFuZCBkaXNwbGF5aW5nIGl0IGFzIGEgYm94cGxvdCAoYmVsb3cpIHdlIGNhbiBiZXR0ZXIgYW5hbHl6ZSB0aGUgYWdlIGFuZCB5ZWFyIHZhcmlhYmxlcy4gRWFjaCB5ZWFyIGlzIGJyb2tlbiBkb3duIGFuZCB0aGUgZGF0YSBjb3JyZWxhdGVkIHdpdGggYWdlIHRvIGJlIGRpc3BsYXllZC4gSnVzdCBieSBsb29raW5nIGF0IHRoZSBwbG90cywgd2UgY2FuIHNlZSB0aGF0IHdoaWxlIHRoZXJlIGlzIG5vdCBhIHNpZ25pZmljYW50IGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgc2Vjb25kIGFuZCB0aGlyZCBxdWFydGlsZXMgYmV0d2VlbiAxOTk5IGFuZCAyMDEyLCBpdCBpcyBjbGVhciB0aGUgbWVkaWFuIGFnZSBmb3IgcnVubmVycyBpbiAyMDEyIGlzIGxvd2VyIHRoYW4gMTk5OS4gQWxzbywgYSBxdWljayBsb29rIGF0IHRoZSBib3hwbG90cyBzaG93cyB0aGUgbWVkaWFuIGFnZSB2YWx1ZSBhcHBlYXJzIHRvIGJlIGdyYWR1YWxseSBkZWNyZWFzaW5nIG92ZXIgdGltZSwgd2l0aCAyMDExIGFzIHRoZSBvbmx5IGV4Y2VwdGlvbi4gVG8gdmVyaWZ5IHRoaXMgd2UgdG9vayBhIGNsb3NlciBsb29rIGF0IHRoZSBib3hwbG90IHN0YXRpc3RpY3MsIHJldmVhbGluZyB0aGUgbWVkaWFuIGFnZSBvZiBydW5uZXJzIGluIDE5OTkgd2FzIDQwLCB3aGlsZSB0aGUgbWVkaWFuIGFnZSBvZiBydW5uZXIgaW4gMjAxMiB3YXMgMzYuIEFub3RoZXIgaW50ZXJlc3RpbmcgbWV0cmljIGlzIHRoZSBudW1iZXIgb2Ygb2JzZXJ2YXRpb25zIGFsc28gaW5jcmVhc2VkIGVhY2ggeWVhciBmcm9tIDMxODkgaW4gMTk5OSB0byA3MTkxIGluIDIwMTIuIFRoZSBkYXRhLCBhcyBzaG93biBpbiB0aGUgYm94cGxvdCwgZG9lcyBub3QgaGF2ZSBhbnkgc2lnbmlmaWNhbnQgb3V0bGllcnMgd2hpY2ggbGVhZHMgdG8gdGhlIGNvbmNsdXNpb24gdGhlIGRhdGEgaXMgcmVsaWFibGUsIGFsb25nIHdpdGggdGhlIGRpc3RyaWJ1dGlvbiBzaG93biBhYm92ZS4gVGhlIGJveHBsb3RzIGhlbHAgc2hvdyBhIGdyYWR1YWwgZGVjbGluZSBpbiB0aGUgYWdlIG9mIHJ1bm5lcnMgb3ZlciB0aW1lLg0KYGBge3J9DQoNCmJwLnAgPC0gZ2dwbG90KGNiTWVuc1Bsb3QsIGFlcyh4PXllYXIsIHk9YWdlLCBmaWxsPXllYXIpKSArIGdlb21fYm94cGxvdCgpICsgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgKyBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gcHJldHR5KGNiTWVuc1Bsb3QkYWdlLCBuID0gMTApKSsNCiAgICBzdGF0X3N1bW1hcnkoZnVuLnk9bWVhbiwgZ2VvbT0icG9pbnQiLCBzaGFwZT01LCBzaXplPTQpDQpicC5wIDwtIGdncGxvdGx5KGJwLnApDQpicC5wDQoNCmBgYA0KDQoNCiMjRGlzY3Vzc2lvbiBhbmQgRnV0dXJlIFdvcmtzDQoNCkluIG91ciBpbml0aWFsIGFuYWx5c2lzIG9mIGFnZSBkaXN0cmlidXRpb24gYWNyb3NzIGFsbCB5ZWFycyBmcm9tIDE5OTkgdG8gMjAxMiwgZm9yIHRoZSBnZW5lcmFsIHBvcHVsYXRpb24gb2YgbWFsZSByYWNlIHJ1bm5lcnMsIHdlIGZpbmQgYSByaWdodC1za2V3ZWQgZGlzdHJpYnV0aW9uIHdpdGggdGhlIGhpZ2hlc3QgZnJlcXVlbmN5IG9mIHJ1bm5lcnMgZmFsbGluZyBpbnRvIHRoZSAzMC00MCB5ZWFycyBhZ2UgYmluLiBVc2luZyBhIHN0YWNrZWQgZGVuc2l0eSBwbG90IHRvIHNob3cgYSBzaW5nbGUgY3VydmUgZm9yIGVhY2ggeWVhciwgdGhlcmUgaXMgYSBub3RhYmxlIGRlY3JlYXNlIGluIG1lYW4gYWdlIGZyb20gMTk5OSB0byByZWNlbnQgeWVhcnMgYW5kIGVhcmxpZXIgeWVhcnMgdGVuZCB0byBoYXZlIGEgbXVjaCBtb3JlIG5vcm1hbCBkaXN0cmlidXRpb24gaW4gYWdlIGNvbXBhcmVkIHRvIHJlY2VudCB5ZWFycy4gRmluZGluZ3Mgc3VwcG9ydCBvcmlnaW5hbCBvYnNlcnZhdGlvbnMgdGhhdCBhZ2Ugc3RlYWRpbHkgZGVjcmVhc2VzIGZyb20gYSBtZWFuIG9mIDQwLjMzNTIgdG8gMzcuNzUyOSB5ZWFycy4gVG8gdGhhdCBlbmQsIHdlIHNwZWN1bGF0ZSB0aGUgZGVjcmVhc2Ugd2lsbCBzbG93IG1vdmluZyBmb3J3YXJkLCBqdXN0IGFzIHdlIGhhdmUgc2VlbiBmcm9tIDIwMDggdG8gMjAxMi4gSW4gYWRkaXRpb24sIGFsdGhvdWdoIG1lYW4gZGlzdHJpYnV0aW9uIGlzIHNoaWZ0aW5nIGxlZnQsIGl0IGlzIGFwcGFyZW50IHRoYXQgcGFydGljaXBhdGlvbiBhbW9uZyBhZ2UgZ3JvdXBzIGFib3ZlIDQwIHllYXJzIGhhcyBubyBzaWduaWZpY2FudCBkZWNyZWFzZS4gVGh1cywgd2UgY2FuIHNlZSBhbiBpbmNyZWFzZSBpbiB0aGUgcmlnaHRseS1za2V3ZWQgZGlzdHJpYnV0aW9uIGZvciBtb3N0IHJlY2VudCB5ZWFycyBvZiB0aGUgcmFjZS4gDQoNClF1YW50aWxlLXF1YW50aWxlIHBsb3RzIGFyZSBuZXh0IHVzZWQgdG8gYXNzZXNzIG5vcm1hbGl0eSBvZiBhZ2UgZGlzdHJpYnV0aW9ucyBhY3Jvc3MgeWVhcnMuIEEgc3RhY2tlZCAoc3RhdGljKSBnZ3Bsb3QgdmlzdWFsIHdhcyBwcm9kdWNlZCwgYnV0IHByb3ZlZCB0b28gY3VtYmVyc29tZSB0byBnbGVhbSBpbnNpZ2h0IGZyb20uIFdlIGNhbiBzZWUgdGhhdCBzZXZlcmFsIHllYXJzIGhhdmUgbm9ybWFsaXR5IGlzc3VlcywgYnV0IGl0IGlzIG5lYXJseSBpbXBvc3NpYmxlIHRvIHVuZGVyc3RhbmQgd2hpY2ggeWVhcnMgdGhlIHBsb3QgcmVmZXJlbmNlcy4gVG8gbWl0aWdhdGUgdGhlc2UgaXNzdWVzLCB3ZSBidWlsdCBhIGdncGxvdCByZW5kZXJpbmcgb2YgZWFjaCB5ZWFyIHRvIGFzc2VzcyBpbmRpdmlkdWFsbHkgYmVmb3JlIG1ha2luZyBjb21wYXJpc29ucy4gV2hpbGUgbm8gcGxvdHMgc2hvdyBwZXJmZWN0IG5vcm1hbGl0eSwgd2Ugb2JzZXJ2ZSBhIHRyZW5kIGluIGFnZSBkaXN0cmlidXRpb25zIGJlY29taW5nIGxlc3Mgbm9ybWFsIG92ZXIgdGltZS4gTG9va2luZyBtb3JlIGNsb3NlbHkgYXQgdGhlc2UgZ2dwbG90IHZpc3VhbGl6YXRpb25zLCB3ZSBzZWUgdGhlIHN0cm9uZ2VzdCBub3JtYWxpdHkgYmV0d2VlbiAzMC02MCB5ZWFycyBvZiBhZ2UgaW4gdGhlIDE5OTkgcmFjZS4gQXMgd2UgbW92ZSB0b3dhcmRzIDIwMDQgYW5kIG1vcmUgcmVjZW50IHllYXJzLCB3ZSBvYnNlcnZlZCBhIGRpcCBiZWxvdyB0aGUgbm9ybWFsaXR5IGxpbmUgYW5kIGEgbGFyZ2VyIHZhcmlhdGlvbiB1bmRlciAzMCB5ZWFycyB0aGFuIHdhcyBzZWVuIHByZXZpb3VzbHkuIFdlIGZpbmQgdGhlIGdyZWF0ZXN0IHZhcmlhdGlvbiBmcm9tIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbiBmb3IgdGhlIDIwMTIgeWVhci4gT3ZlcmFsbCwgdGhlIHF1YW50aWxlLXF1YW50aWxlIHBsb3Qgb3V0Y29tZXMgZnVydGhlciBzdXBwb3J0IGZpbmRpbmdzIHByb3ZpZGVkIGZyb20gZGVuc2l0eSBjdXJ2ZXMgaW4gdGhhdCBub3JtYWxpdHkgaW4gYWdlIGRpc3RyaWJ1dGlvbnMgaXMgYmVnaW5uaW5nIHRvIHNoaWZ0LiBXZSBhbHNvIG5vdGUgdGhhdCBpbiBtb3JlIHJlY2VudCB5ZWFycyB3ZSBiZWdpbiB0byBoYXZlIGEgc2tld2VkIGRpc3RyaWJ1dGlvbiwgbGlrZWx5IGNhdXNlZCBieSBpbmNyZWFzZWQgcGFydGljaXBhdGlvbiBvZiB5b3VuZ2VyIGluZGl2aWR1YWxzLiANCg0KTGFzdGx5LCBib3hwbG90cyBhcmUgdXRpbGl6ZWQgdG8gYmV0dGVyIGFuYWx5emUgdGhlIGFnZSBhbmQgeWVhciB2YXJpYWJsZXMuIFRoZSBtb3N0IGFwcGFyZW50IHRyZW5kIHdhcyB0aGF0IG1lZGlhbiBhZ2UgZ3JhZHVhbGx5IGRlY3JlYXNlcyBvdmVyIHRpbWUsIGV4Y2x1ZGluZyAyMDExLiBXaGlsZSBubyBzaWduaWZpY2FudCBkaWZmZXJlbmNlIHdhcyBzZWVuIGJldHdlZW4gdGhlIHNlY29uZCBhbmQgdGhpcmQgcXVhcnRpbGVzIGZyb20gMTk5OSB0byAyMDEyLCBtZWRpYW4gYWdlIGluIDIwMTIgaXMgbG93ZXIgdGhhbiAxOTk5ICgzNiBhbmQgNDAsIHJlc3BlY3RpdmVseSkuIFdlIGFsc28gZmluZCB0aGF0IHRoZSBudW1iZXIgb2Ygb2JzZXJ2YXRpb25zIGluY3JlYXNlcyB5ZWFyIG92ZXIgeWVhciBmcm9tIDMsMTg5IGluIDE5OTkgdG8gNywxOTEgaW4gMjAxMi4gSG93ZXZlciwgYm94cGxvdCByZXByZXNlbnRhdGlvbnMgb2YgdGhlIGRhdGEgc2hvdyBubyBzaWduaWZpY2FudCBvdXRsaWVycywgcHJvdmlkaW5nIHN0cm9uZyBldmlkZW5jZSB0aGF0IHRoZSBkYXRhIHdhcyBjb3JyZWN0bHkgZm9ybWF0dGVkIGFuZCBpcyByZWxpYWJsZS4gVGhlcmVmb3JlLCBmaW5hbCBjb21wYXJpc29ucyBvZiBhZ2UgZGlzdHJpYnV0aW9uIGFjcm9zcyAxNCB5ZWFycyBvZiB0aGUgQ2hlcnJ5IEJsb3Nzb20gVGVuIE1pbGUgUnVuIHVzaW5nIGRlbnNpdHkgY3VydmVzLCBxdWFudGlsZS1xdWFudGlsZSBwbG90cywgYW5kIGJveHBsb3RzIHJldmVhbCBhbiBvdmVyYWxsIGdyYWR1YWwgZGVjbGluZSBpbiB0aGUgYWdlIG9mIHJ1bm5lcnMgb3ZlciB0aW1lLiBBcyBhbiBleHRlbnNpb24gb2YgdGhpcyBlZmZvcnQsIGZ1dHVyZSB3b3JrcyB3b3VsZCBpbmNsdWRlIG1vZGVsaW5nIHBlcmZvcm1hbmNlIG1ldHJpY3MgYW5kIGFnZSBkaXN0cmlidXRpb25zIHVzaW5nIGRpZmZlcmVudCB2aXN1YWxpemF0aW9ucy4gV2UgbWlnaHQgY29uc2lkZXIgZXZhbHVhdGluZyBhZ2UgZGlzdHJpYnV0aW9uIGFjcm9zcyBlYWNoIHllYXIgdXNpbmcgcmVzaWR1YWwgcGxvdHMgb3IgaGVhdCBtYXBzLiBSZXN1bHRzIHdvdWxkIHRoZW4gYmUgZXZhbHVhdGVkIGFuZCBjb21wYXJlZCBhZ2FpbnN0IHRoZSBkZW5zaXR5IGN1cnZlcywgcXVhbnRpbGUtcXVhbnRpbGUgcGxvdHMsIGFuZCBib3hwbG90cyBhbmFseXNlcyB0byBnYWluIGRlZXBlciBpbnNpZ2h0IGFuZCBsaWtlbHkgcmVpbmZvcmNlIGZpbmRpbmdzLiANCg0KDQojIyBSZWZlcmVuY2VzDQpbMV0gRC4gTGFuZyBhbmQgRC4gTm9sYW4sIERhdGEgU2NpZW5jZSBpbiBSOiBBIENhc2UgU3R1ZGllcyBBcHByb2FjaCB0byBDb21wdXRhdGlvbiBSZWFzb25pbmcgYW5kIFByb2JsZW0gU29sdmluZy4gTmV3IFlvcmssIE5ldyBZb3JrOiBDUkMgUHJlc3MuIA0K